//
// Created by LiuYou on 2021/11/14.
//

#include <iostream>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>


static int fd;
static void* mmapAddress;
static off_t fileSize;


int main(int argc, char** argv) {
    if (argc < 2) {
        fprintf( stderr, "用法: %s filename\n", argv[0] );
        return 1;
    }


    fd = open( argv[1], O_RDONLY );
    if (fd < 0) {
        perror( "open()" );
        return 1;
    }
//    atexit( [] {
//        close( fd );
//    } );

    // 计算文件的大小方法有很多种。

#ifdef calculate_file_size_lseek
    //region 这个是使用 lseek();函数。
    off_t fileSize = lseek( fd, 0, SEEK_END );
    lseek( fd, 0, SEEK_SET );
    //endregion
#endif


#ifdef calculate_file_size_fstat
    struct stat statResult;
    fstat( fd, &statResult );
    off_t fileSize = statResult.st_size;
#endif


    struct stat statResult;
    fstat( fd, &statResult );
    fileSize = statResult.st_size;

    fprintf( stdout, "文件的大小为: %ld\n", fileSize );


    mmapAddress = mmap( nullptr, fileSize, PROT_READ, MAP_PRIVATE, fd, 0 );
    if (mmapAddress == MAP_FAILED) {
        perror( "mmap()" );
        return 1;
    }
    atexit( [] {
        munmap( mmapAddress, fileSize );
    } );

    // 调用 mmap();成功之后, 这个 fd 如果后续不使用了就可以关掉了。
    close( fd );

    char* str = static_cast<char*>(mmapAddress);

    int count = 0;
    for (int i = 0; i < fileSize; ++i) {
        if (str[i] == 'a') {
            ++count;
        }
    }

    fprintf( stdout, "当前文件有 %d 个字符 a 。\n", count );


    return 0;
}
